#include "RAT_RendererDX9.h"


static LRESULT CALLBACK MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );


namespace RAT_ENGINE
{
	RAT_RendererDX9::RAT_RendererDX9() : hWnd(0), g_pD3D(NULL), g_pd3dDevice(NULL)
	{
	}

	RAT_RendererDX9::~RAT_RendererDX9()
	{
	}

	void RAT_RendererDX9::Init(RAT_WindowManager* argWMan)
	{	
		wMan = argWMan;
		// Register the window class
		WNDCLASSEX wndClass =
		{
		    sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0, 0,
		    GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
		    "foo", NULL
		};
		wc = wndClass;

		RegisterClassEx( &wc );

		hWnd = CreateWindow( "foo", argWMan->GetWindow(0)->GetName().c_str(),
			WS_OVERLAPPEDWINDOW, argWMan->GetWindow(0)->GetX(), argWMan->GetWindow(0)->GetY(), 
			argWMan->GetWindow(0)->GetWidth(), argWMan->GetWindow(0)->GetHeight(),
                             NULL, NULL, wc.hInstance, NULL );

		// Create the D3D object, which is needed to create the D3DDevice.
		g_pD3D = (LPDIRECT3D9)Direct3DCreate9( D3D_SDK_VERSION );

		// Set up the structure used to create the D3DDevice. Most parameters are
		// zeroed out. We set Windowed to TRUE, since we want to do D3D in a
		// window, and then set the SwapEffect to "discard", which is the most
		// efficient method of presenting the back buffer to the display.  And 
		// we request a back buffer format that matches the current desktop display 
		// format.
		D3DPRESENT_PARAMETERS d3dpp;
		ZeroMemory( &d3dpp, sizeof( d3dpp ) );
		d3dpp.Windowed = TRUE;
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
		d3dpp.BackBufferHeight = 1024;
		d3dpp.BackBufferWidth = 768;

		// Create the Direct3D device. Here we are using the default adapter (most
		// systems only have one, unless they have multiple graphics hardware cards
		// installed) and requesting the HAL (which is saying we want the hardware
		// device rather than a software one). Software vertex processing is 
		// specified since we know it will work on all cards. On cards that support 
		// hardware vertex processing, though, we would see a big performance gain 
		// by specifying hardware vertex processing.
		std::cout << g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                              D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                              &d3dpp, &g_pd3dDevice );
		DWORD err = GetLastError();
	}

	void RAT_RendererDX9::CleanUp()
	{
		g_pd3dDevice->Release();
		g_pD3D->Release();

		UnregisterClass( "D3D Tutorial", wc.hInstance );
	}

	void RAT_RendererDX9::Render()
	{
		// Clear the backbuffer to a blue color
		g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

		// Begin the scene
		g_pd3dDevice->BeginScene();

		// End the scene
		g_pd3dDevice->EndScene();
		
		// Present the backbuffer contents to the display
		g_pd3dDevice->Present( NULL, NULL, hWnd, NULL );
	}	

	void RAT_RendererDX9::ShowWin()
	{
		ShowWindow( hWnd, SW_SHOWDEFAULT );
		UpdateWindow( hWnd );

		// Enter the message loop
		MSG msg;
		while( GetMessage( &msg, NULL, 0, 0 ) )
		
		{
			if (PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
			{
		    TranslateMessage( &msg );
		    DispatchMessage( &msg );
			}
			else
			{
				Render();
			}
		}
	}
}

LRESULT CALLBACK MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
			//CleanUp();
            PostQuitMessage( 0 );
            return 0;

        case WM_PAINT:
            //Render();
            ValidateRect( hWnd, NULL );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

